using System;
using System.ComponentModel;

namespace ScienceNET.Optimization
{   

public class OptimizerGM : OptimizerBase
    {
        public double eta = 0.01;
        public double alfa = 0.9;
        private double[] parametersDelta;


        /// <summary>
        /// Initializes an optimizer for a selected object
        /// </summary>
        /// <param name="optimizedObject">The object which parameters will be optimzed.</param>
        public OptimizerGM(IOpimizable optimizedObject)
        {
            if ((optimizedObject.AllowedComputations & ComputeEnum.Gradient) == 0 || (optimizedObject.AllowedComputations & ComputeEnum.FunctionValue) == 0)
                throw new Exception("The resilient backpropagation optimizer needs a funcion value and a gradient from a model");
         
   
            this.parametersNumber = optimizedObject.ParametersNumber;
            this.parametersDelta = new double[this.parametersNumber];
            
            this.parameters = new double[this.parametersNumber];
            this.gradient = new double[this.parametersNumber];

            for (int parameter = 0; parameter < this.parametersNumber; parameter++) parametersDelta[parameter] = 0.0;
            this.optimizedObject = optimizedObject;
        }

        public override void Step()
        {
            this.optimizedObject.Compute(ComputeEnum.FunctionValue | ComputeEnum.Gradient, this);
            
            for (int parameter = 0; parameter < this.parametersNumber; parameter++)
            {
                this.parametersDelta[parameter] = alfa * this.parametersDelta[parameter] - eta *  this.gradient[parameter];
                this.parameters[parameter] += this.parametersDelta[parameter];
            }

        }

}
}